package com.enhe.gck.calculate;

import com.enhe.gck.pojo.Config;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
import java.util.Optional;

/**
 * 计算过磅误差
 */
@Slf4j
public class WeightErrorCalculation {

    /**
     * 净重误差值计算
     *
     * @param planWeight               订单计划重量
     * @param customIntervalOptional   自定义净重误差区间配置
     * @param defaultNetErrorMaxConfig 默认净重误差最大值配置
     * @return 净重误差值
     */
    public static BigDecimal calculateNetWeightErrorValue(BigDecimal planWeight, Optional<Config> customIntervalOptional, Config defaultNetErrorMaxConfig) {
        BigDecimal defaultValue = new BigDecimal(defaultNetErrorMaxConfig.getValue()).multiply(planWeight).setScale(3, RoundingMode.HALF_UP);
        if (Objects.isNull(customIntervalOptional) || !customIntervalOptional.isPresent()) {
            log.warn("未设置自定义净重误差计算规则，使用默认净重误差最大值配置：[{}]", defaultValue);
            return defaultValue;
        }
        // 获取自定义净重误差区间配置，格式："0<x<=15,kg:60;15<x<=30,‰:3;30<x<60,‰:5;60<=x,‰:2"
        String ruleIntervalStr = customIntervalOptional.get().getValue();

        String[] ruleIntervalArr = ruleIntervalStr.split(";");
        for (String rule : ruleIntervalArr) {
            boolean isMatch = false;
            String[] upDownArr = rule.substring(0, rule.indexOf(",")).split("x");
            if (upDownArr[0].contains("<=")) {
                if (planWeight.compareTo(BigDecimal.valueOf(Double.parseDouble(upDownArr[0].replace("<=", "")))) >= 0) {
                    isMatch = matchUpCheck(upDownArr, planWeight);
                }
            } else {
                if (planWeight.compareTo(BigDecimal.valueOf(Double.parseDouble(upDownArr[0].replace("<", "")))) > 0) {
                    isMatch = matchUpCheck(upDownArr, planWeight);
                }
            }

            if (isMatch) {
                String value = rule.substring(rule.indexOf(":") + 1);
                BigDecimal v = BigDecimal.valueOf(Double.parseDouble(value)).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP);
                if (rule.contains("kg")) {
                    log.warn("命中净重误差计算规则：[{}]，计划重量：[{}]，净重误差值：[{}]", rule, planWeight, v);
                    return v;
                } else {
                    BigDecimal v2 = planWeight.multiply(v).setScale(3, RoundingMode.HALF_UP);
                    log.warn("命中净重误差计算规则：[{}]，计划重量：[{}]，净重误差值：[{}]", rule, planWeight, v2);
                    return v2;
                }
            }
        }

        log.warn("未设置自定义净重误差计算规则，使用默认净重误差最大值配置：[{}]", defaultValue);
        return defaultValue;
    }

    private static boolean matchUpCheck(String[] upDownArr, BigDecimal planWeight) {
        boolean isMatch = false;
        if (upDownArr.length > 1) {
            if (upDownArr[1].contains("<=")) {
                if (planWeight.compareTo(BigDecimal.valueOf(Double.parseDouble(upDownArr[1].replace("<=", "")))) <= 0) {
                    isMatch = true;
                }
            } else {
                if (planWeight.compareTo(BigDecimal.valueOf(Double.parseDouble(upDownArr[1].replace("<", "")))) < 0) {
                    isMatch = true;
                }
            }
        } else {
            isMatch = true;
        }
        return isMatch;
    }

    public static int calculateOverLoad(BigDecimal planWeight, BigDecimal net, BigDecimal singleWeigh) {
        BigDecimal overNumber = (net.subtract(planWeight)).divide(singleWeigh, 3, RoundingMode.HALF_UP);
        int intValue = overNumber.intValue();
        BigDecimal decimal = overNumber.remainder(BigDecimal.ONE);
        // 不足25公斤不算一袋，大于25公斤折算一袋
        if (decimal.compareTo(BigDecimal.valueOf(0.5)) >= 0) {
            intValue = intValue + 1;
        }
        return intValue;
    }

    public static int calculateUnderLoad(BigDecimal planWeight, BigDecimal net, BigDecimal singleWeigh) {
        BigDecimal underLoad = (planWeight.subtract(net)).divide(singleWeigh, 3, RoundingMode.HALF_UP);
        int intValue = underLoad.intValue();
        BigDecimal decimal = underLoad.remainder(BigDecimal.ONE);
        // 不足25公斤不算一袋，大于25公斤折算一袋
        if (decimal.compareTo(BigDecimal.valueOf(0.5)) >= 0) {
            intValue = intValue + 1;
        }
        return intValue;
    }

    public static BigDecimal calculateEmptyLeaving(Optional<Config> emptyLeavingConfigOptional, Config netErrorMaxConfig, BigDecimal planWeight) {
        if (!emptyLeavingConfigOptional.isPresent()) {
            return new BigDecimal(netErrorMaxConfig.getValue()).multiply(planWeight).setScale(3, RoundingMode.HALF_UP);
        }
        return new BigDecimal(emptyLeavingConfigOptional.get().getValue());
    }
}
